package com.fram.common.util.tencent;

import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.fram.common.canstant.ErrCode;
import com.fram.common.exception.ProAffairException;
import com.fram.common.exception.ProException;
import com.fram.common.exception.ProRunTimeException;
import com.fram.common.exception.ProValiDataException;
import com.fram.common.redis.RedisService;
import com.fram.common.util.PublicMethod;
import com.fram.common.util.http.HttpClientTools;
import com.fram.common.util.json.JSONTools;
import com.fram.entity.SysResourceAccont;
import com.fram.mapper.SysResourceAccontMapper;

@Component
@EnableAsync
public class TencentUtils {

	private static Logger LOG = LoggerFactory.getLogger(TencentUtils.class);

	@Autowired
	private RedisService redisService;

	public static final int ACCESS_TOKEN_REDIS_DB = 2;

	@Autowired
	private SysResourceAccontMapper resourceAccontMapper;

	/**
	 * 获取token
	 *
	 * @param appId
	 *            小程序appId
	 * @return 返回为null网络异常
	 */
	public String getToken(String appId) throws ProException {
		String tokenKey = appId + "_access_token";
		String token = (String) redisService.get(ACCESS_TOKEN_REDIS_DB, tokenKey);
		if (!StringUtils.isEmpty(token)) {
			return token;
		}
		// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
		SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);

		String url;
		if (mTenConfigBean.getType() == 1 || mTenConfigBean.getType() == 2) {
			url = "https://api.weixin.qq.com/cgi-bin/token";
		} else {
			url = "https://api.q.qq.com/api/getToken";
		}
		Map<String, Object> map = new HashMap<>();
		map.put("appid", appId);
		map.put("secret", mTenConfigBean.getSecret());
		map.put("grant_type", "client_credential");
		String mValue = HttpClientTools.get(url + "?", null, map);
		TencentTokenBean mTencentTokenBean = JSONTools.jsonStr2obj(mValue, TencentTokenBean.class);
		if (mTencentTokenBean == null || mTencentTokenBean.getErrcode() != 0) {
			throw new ProValiDataException("获取token失败：" + mValue);
		}
		// 少存10分钟
		redisService.set(ACCESS_TOKEN_REDIS_DB, tokenKey, mTencentTokenBean.getAccess_token(), mTencentTokenBean.getExpires_in() - 1000);
		return mTencentTokenBean.getAccess_token();
	}

	/**
	 * 获取用户openId
	 *
	 * @param appId
	 *            小程序appId
	 * @param code
	 *            登录凭证code 前端登录获取
	 * @return 返回为null网络异常
	 */
	public TencentLoginBean getOpenId(String appId, String code) throws ProAffairException {
		String url;
		// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
		SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);
		if (mTenConfigBean.getType() == 1) {
			url = "https://api.weixin.qq.com/sns/jscode2session";
		} else {
			url = "https://api.q.qq.com/sns/jscode2session";
		}
		Map<String, Object> map = new HashMap<>();
		map.put("appid", appId);
		map.put("secret", mTenConfigBean.getSecret());
		map.put("js_code", code);
		map.put("grant_type", "authorization_code");
		String responseBody = HttpClientTools.get(url + "?", null, map);
		return JSONTools.jsonStr2obj(responseBody, TencentLoginBean.class);
	}

	/**
	 * 获取用户openId
	 *
	 * @param appId
	 *            小程序appId
	 * @param code
	 *            登录凭证code 前端登录获取
	 * @return 返回为null网络异常
	 */
	public WechatAccessToken getH5OpenId(String appId, String code) throws ProRunTimeException {
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
		// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
		SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);
		Map<String, Object> map = new HashMap<>();
		map.put("appid", appId);
		map.put("secret", mTenConfigBean.getSecret());
		map.put("code", code);
		map.put("grant_type", "authorization_code");
		String responseBody = HttpClientTools.get(url + "?", null, map);
		LOG.info("-腾讯-getH5OpenId->{}", responseBody);
		return JSONTools.jsonStr2obj(responseBody, WechatAccessToken.class);
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月15日 下午2:34:08 @版本：V1.0 @description：-> 公众号获取用户信息
	 */
	public WechatUserInfo getWechatUserInfo(String accToken, String openId) throws ProAffairException {
		try {
			String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accToken + "&openid=" + openId + "&lang=zh_CN";
			String responseBody = HttpClientTools.get(url, null, null);
			return JSONTools.jsonStr2obj(responseBody, WechatUserInfo.class);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 异步发送订阅消息
	 **/
	@Async
	public Future<String> sendWinLuckMessage(String appId, String openId, Map<String, Object> param) throws ProException {
		// 获取token
		String accToken = getToken(appId);
		if (StringUtils.isEmpty(accToken)) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "获取TOKEN失败！");
		}
		// 发送订阅消息
		param.put("access_token", accToken);
		String sendUrl = null;
		if (PublicMethod.isNumber(appId)) {// QQ
			sendUrl = "https://api.q.qq.com/api/json/subscribe/SendSubscriptionMessage?access_token=" + accToken;
		} else {
			sendUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accToken;
		}
		String response = HttpClientTools.post(sendUrl, null, null, JSONTools.obj2json(param));
		return new AsyncResult<String>(response);
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月11日 上午10:16:13 @版本：V1.0 @description：-> 前端JsSdk签名
	 */
	public String getJsSdkTicketToken(String appId) throws ProException {
		String tokenKey = appId + "_ticket_token";
		String token = (String) redisService.get(ACCESS_TOKEN_REDIS_DB, tokenKey);
		if (!StringUtils.isEmpty(token)) {
			return token;
		}
		String jsapiUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getToken(appId) + "&type=jsapi";
		String jsapiResponse = HttpClientTools.get(jsapiUrl, null, null);
		if (StringUtils.isEmpty(jsapiResponse)) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "获取JSSDK的ticket签名失败");
		}
		Map<String, Object> map = JSONTools.convertJsonStrToMap(jsapiResponse);
		if (map == null || !"ok".equals(map.get("errmsg"))) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "获取JSSDK的ticket签名失败:" + jsapiResponse);
		}
		redisService.set(ACCESS_TOKEN_REDIS_DB, tokenKey, map.get("ticket").toString(), Integer.parseInt(map.get("expires_in").toString()) - 1000);
		return map.get("ticket").toString();
	}

	/**
	 * 支付过后获取Unionid
	 **/
	public String getUnionid(String appId, String openId, String transactionId) throws ProException {
		String unionid = null;
		// 获取token
		String accToken = getToken(appId);
		if (StringUtils.isEmpty(accToken)) {
			return unionid;
		}
		String url = null;
		// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
		SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);
		if (mTenConfigBean.getType() == 1) {
			url = "https://api.weixin.qq.com/wxa/getpaidunionid?access_token=" + accToken + "&openid=" + openId + "&transaction_id=" + transactionId;
		}
		if (!StringUtils.isEmpty(url)) {
			String response = HttpClientTools.get(url, null, null);
			if (!StringUtils.isEmpty(response)) {
				Map<String, Object> resp = JSONTools.convertJsonStrToMap(response);
				if (resp != null && !org.springframework.util.StringUtils.isEmpty(resp.get("unionid"))) {
					return resp.get("unionid").toString();
				}
			}
		}
		return unionid;
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年10月21日 上午10:46:36 @版本：V1.0 @description：-> 检测违规内容
	 */
	public void checkMsg(String content) throws ProException {
		try {
			String appId = "wx61407be355c01f7a";
			// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
			SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);
			if (mTenConfigBean.getIsVerificationContent() == 0) {
				return;
			}
			String url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + getToken(appId);
			Map<String, Object> map = new HashMap<>();
			map.put("content", content);
			String response = HttpClientTools.post(url, null, null, JSONTools.obj2json(map));
			LOG.info(response + "-------------验证效果");
			if (!response.contains("ok")) {
				throw new ProValiDataException("违规内容");
			}
		} catch (ProException e) {
			throw new ProValiDataException(e.getErrorMsg());
		} catch (Exception e) {
			e.printStackTrace();
			LOG.error("----------------调用腾讯内容过滤系统出错------------------");
			throw new ProValiDataException("调用腾讯内容过滤系统出错");
		}
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年10月21日 上午10:46:36 @版本：V1.0 @description：-> 检测违规内容
	 */
	public void checkImg(MultipartFile multipartFile) throws ProException {
		try {
			String appId = "wx61407be355c01f7a";
			// TenConfigBean mTenConfigBean = TenConfig.getConfig(appId);
			SysResourceAccont mTenConfigBean = resourceAccontMapper.selectByAppId(appId);
			if (mTenConfigBean.getIsVerificationImage() == 0) {
				return;
			}
			BufferedImage sourceImg = javax.imageio.ImageIO.read(multipartFile.getInputStream());
			int width = sourceImg.getWidth();
			int height = sourceImg.getHeight();
			if (width < height && (width > 750 || height > 1334)) {
				throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "文件图片超出尺寸");
			}
			if (width > height && (height > 750 || width > 1334)) {
				throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "文件图片超出尺寸");
			}
			CloseableHttpClient httpclient = HttpClients.createDefault();
			CloseableHttpResponse response = null;
			HttpPost request = new HttpPost("https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + getToken(appId));
			request.addHeader("Content-Type", "application/octet-stream");
			InputStream inputStream = multipartFile.getInputStream();
			byte[] byt = new byte[inputStream.available()];
			inputStream.read(byt);
			request.setEntity(new ByteArrayEntity(byt, org.apache.http.entity.ContentType.create("image/jpg")));
			response = httpclient.execute(request);
			HttpEntity httpEntity = response.getEntity();
			String result = EntityUtils.toString(httpEntity, "UTF-8");// 转成string
			JSONObject jso = JSONObject.parseObject(result);
			LOG.info(jso + "-------------验证效果");
			Object errcode = jso.get("errcode");
			int errCode = (int) errcode;
			if (errCode != 0) {
				LOG.error("图片内容违规-----------");
				throw new ProValiDataException("违规图片");
			}
		} catch (ProException e) {
			throw new ProValiDataException(e.getErrorMsg());
		} catch (Exception e) {
			e.printStackTrace();
			LOG.error("----------------调用腾讯内容过滤系统出错------------------");
			throw new ProValiDataException("调用腾讯内容过滤系统出错");
		}
	}

	public static void main(String[] args) {
		// TenConfigBean mTenConfigBean = TenConfig.getConfig("wx61407be355c01f7a");
		// String url1;
		// if (mTenConfigBean.type == 1 || mTenConfigBean.type == 2) {
		// url1 = "https://api.weixin.qq.com/cgi-bin/token";
		// } else {
		// url1 = "https://api.q.qq.com/api/getToken";
		// }
		// Map<String, Object> map = new HashMap<>();
		// map.put("appid", "wx61407be355c01f7a");
		// map.put("secret", mTenConfigBean.secret);
		// map.put("grant_type", "client_credential");
		// String mValue = HttpClientTools.get(url1 + "?", null, map);
		// System.out.println(mValue);

		// String token = "38_0Qv1wx-bgHBWm_iG-ZicwwnqBlgIASCoU8oSzTGGB7obcQVKh2QN-vuGv-uah_bRFoL44XieNmwNsBxqTPmIm32mE42IIRxMRWpRz_ryXvtN__5NvKTDoLRI3USFFhIhe1uUtMr6wn4PIYXTZQJiAJARIB";
		// String url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + token;
		// Map<String, Object> map = new HashMap<>();
		// map.put("content", "meichig没吃过好东西生奸内射那玩意儿");
		// System.out.println(HttpClientTools.post(url, null, null, JSONTools.obj2json(map)));
	}
}
